/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;
import org.springframework.lang.Nullable;

/**
 * A BeanDefinition describes a bean instance, which has property values,
 * constructor argument values, and further information supplied by
 * concrete implementations.
 *
 * <p>This is just a minimal interface: The main intention is to allow a
 * {@link BeanFactoryPostProcessor} such as {@link PropertyPlaceholderConfigurer}
 * to introspect and modify property values and other bean metadata.
 *
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @since 19.03.2004
 * @see ConfigurableListableBeanFactory#getBeanDefinition
 * @see org.springframework.beans.factory.support.RootBeanDefinition
 * @see org.springframework.beans.factory.support.ChildBeanDefinition
 *
 *定义了Bean的各种信息
 */
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	/**
	 * 单例Bean还是原型Bean
	 */
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;


	/**
	 * 应用程序重要组成部分
	 */
	int ROLE_APPLICATION = 0;

	/**
	 * 做为大量配置的一部分（支持、扩展类）  实际上就是说，我这个Bean是用户的，是从配置文件中过来的。
	 */
	int ROLE_SUPPORT = 1;

	/**
	 * 指内部工作的基础构造  实际上是说我这Bean是Spring自己的，和你用户没有一毛钱关系
	 */
	int ROLE_INFRASTRUCTURE = 2;


	// Modifiable attributes

	/**
	 * 若存在父类的话，就设置进去
	 */
	void setParentName(@Nullable String parentName);

	@Nullable
	String getParentName();

	/**
	 * Specify the bean class name of this bean definition.
	 * <p>The class name can be modified during bean factory post-processing,
	 * typically replacing the original class name with a parsed variant of it.
	 * @see #setParentName
	 * @see #setFactoryBeanName
	 * @see #setFactoryMethodName
	 */
	void setBeanClassName(@Nullable String beanClassName);
	@Nullable
	String getBeanClassName();

	/**
	 * Override the target scope of this bean, specifying a new scope name.
	 * @see #SCOPE_SINGLETON
	 * @see #SCOPE_PROTOTYPE
	 */
	void setScope(@Nullable String scope);
	@Nullable
	String getScope();

	/**
	 * @Lazy 是否需要懒加载
	 */
	void setLazyInit(boolean lazyInit);

	boolean isLazyInit();

	/**
	 *
	 * 所依赖的bean的名称，如果有多个依赖的bean,这里需要都列出来。容器会保证这些被依赖的bean先被初始化。
	 */
	void setDependsOn(@Nullable String... dependsOn);
	@Nullable
	String[] getDependsOn();

	/**
	 * Set whether this bean is a candidate for getting autowired into some other bean.
	 * <p>Note that this flag is designed to only affect type-based autowiring.
	 * It does not affect explicit references by name, which will get resolved even
	 * if the specified bean is not marked as an autowire candidate. As a consequence,
	 * autowiring by name will nevertheless inject a bean if the name matches.
	 *
	 * 这个Bean是否允许被自动注入到别的地方去（默认都是被允许的）,
	 * 注意：此标志只影响按类型装配，不影响byName的注入方式的~~~~
	 */
	void setAutowireCandidate(boolean autowireCandidate);
	boolean isAutowireCandidate();

	/**
	 *
	 * 当前bean定义是否主bean。当某个自动绑定遇到多个候选bean时,@Primary属性为true的会被使用。
	 */
	void setPrimary(boolean primary);
	boolean isPrimary();

	/**
	 * Specify the factory bean to use, if any.
	 * This the name of the bean to call the specified factory method on.
	 * @see #setFactoryMethodName
	 *
	 * 如果要使用factory bean来创建bean,这里指定了相应的工厂bean的类名称
	 */
	void setFactoryBeanName(@Nullable String factoryBeanName);
	@Nullable
	String getFactoryBeanName();


	/**
	 * Specify a factory method, if any. This method will be invoked with
	 * constructor arguments, or with no arguments if none are specified.
	 * The method will be invoked on the specified factory bean, if any,
	 * or otherwise as a static method on the local bean class.
	 * @see #setFactoryBeanName
	 * @see #setBeanClassName
	 *  工厂方法名称。
	 *  基于类静态工厂方法的情况下，结合beanClassName使用;
	 *  基于工厂bean的情况下，结合factoryBeanName使用。
	 *  如果bean定义的constructorArgumentValues有内容，工厂方法被调用时会使用该属性。
	 */
	void setFactoryMethodName(@Nullable String factoryMethodName);
	@Nullable
	String getFactoryMethodName();


	/**
	 * Return the constructor argument values for this bean.
	 * <p>The returned instance can be modified during bean factory post-processing.
	 * @return the ConstructorArgumentValues object (never {@code null})
	 *  获取此Bean的构造函数参数值们
	 */
	ConstructorArgumentValues getConstructorArgumentValues();
	/**
	 * @since 5.0.2
	 */
	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

	/**
	 *
	 * 获取普通属性的集合
	 */
	MutablePropertyValues getPropertyValues();
	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}

	/**
	 * Set the name of the initializer method.
	 * @since 5.1
	 *
	 * bean的初始化方法
	 */
	void setInitMethodName(@Nullable String initMethodName);
	@Nullable
	String getInitMethodName();

	/**
	 * Set the name of the destroy method.
	 * @since 5.1
	 * bean的析构方法
	 */
	void setDestroyMethodName(@Nullable String destroyMethodName);
	@Nullable
	String getDestroyMethodName();

	/**
	 * Set the role hint for this {@code BeanDefinition}. The role hint
	 * provides the frameworks as well as tools with an indication of
	 * the role and importance of a particular {@code BeanDefinition}.
	 * @since 5.1
	 * @see #ROLE_APPLICATION
	 * @see #ROLE_SUPPORT
	 * @see #ROLE_INFRASTRUCTURE
	 *
	 * APPLICATION – 指出该bean是应用程序的主要部分，通常对应用户定义的bean。
	 * SUPPORT – 应用支持性质的bean,在某些地方比较重要，但从整个应用的返回来看，还没那么重要。
	 * INFRASTRUCTURE – 基础设施bean,仅仅用于框架内部工作，跟终端用户无关。
	 *
	 * bean的角色:APPLICATION,SUPPORT,INFRASTRUCTURE。提示框架该bean的角色和重要程度。
	 */
	void setRole(int role);
	int getRole();

	/**
	 * @since 5.1
	 * bean的描述
	 */
	void setDescription(@Nullable String description);
	@Nullable
	String getDescription();


	// Read-only attributes

	/**
	 * 作用域断言，是否singleton
	 */
	boolean isSingleton();

	/**
	 * 	作用域断言，是否prototype
	 */
	boolean isPrototype();

	/**
	 * Return whether this bean is "abstract", that is, not meant to be instantiated.
	 * 是否抽象bean定义,抽象bean定义的目的不是用于实例化bean,而是有其他目的。
	 */
	boolean isAbstract();

	/**
	 * Return a description of the resource that this bean definition
	 * came from (for the purpose of showing context in case of errors).
	 * 资源描述文本，告知当前bean定义的来源，一般用于错误时显示上下文。
	 */
	@Nullable
	String getResourceDescription();

	/**
	 * Return the originating BeanDefinition, or {@code null} if none.
	 * Allows for retrieving the decorated bean definition, if any.
	 * <p>Note that this method returns the immediate originator. Iterate through the
	 * originator chain to find the original BeanDefinition as defined by the user.
	 *
	 * 返回来源bean定义(如果有的话)。通过该属性，可以获取被修饰的bean定义。
	 * 需要注意的是该属性仅仅返回直接来源bean定义而不是返回最深处的来源bean定义。
	 * 一个bean定义的originatingBeanDefinition属性隐含了一个来源bean定义链，通过迭代访问该链，
	 * 可以最终找到最终来自用户的bean定义。
	 */
	@Nullable
	BeanDefinition getOriginatingBeanDefinition();

}
